using System;
using System.Text.RegularExpressions;

namespace Microsoft.Services.TfsAlert.Core
{
    /// <summary>
    /// Helper object that extracts information from a URI string and places into its components
    /// Protocol, Server and Port
    /// </summary>
    public sealed partial class TfsServerInfoHelper
    {
        private const string DEFAULT_FORMAT_ERROR = "URI must be in the format: 'Protocol://server:port'";

        private System.Text.RegularExpressions.Regex _regex;
        private string _uriString;
        private string _server;
        private int _port;
        private string _protocol;

        /// <summary>
        /// Constructor that extracts component information from the URI string
        /// </summary>
        /// <param name="uriString">URI information</param>
        public TfsServerInfoHelper(string uriStringIn)
        {
            string uriString;
            string port;

            if (uriStringIn == null)
            {
                throw new ArgumentException("URI string must contain a valid non-blank URI");
            }

            uriString = uriStringIn.Trim();

            if (string.IsNullOrEmpty(uriString))
            {
                throw new ArgumentException("URI string must contain a valid non-blank URI");
            }

            // Hold the string in lower case
            _uriString = uriString.ToLower().Trim();

            // use a regular expression to extract protocol, server and port information
            _regex = new Regex(@"^(?<proto>https?)://(?<server>[\w|\d|\.]*):?(?<port>\d+)?/*",
                    RegexOptions.Compiled);

            // Pull all of the information out into the component parts
            try
            {
                _protocol = _regex.Match(_uriString).Result("${proto}");
                _server = _regex.Match(_uriString).Result("${server}");
                port = _regex.Match(_uriString).Result("${port}");
            }
            catch (Exception)
            {
                throw new ArgumentException(DEFAULT_FORMAT_ERROR);
            }

            if ((string.IsNullOrEmpty(_server) || (string.IsNullOrEmpty(_server))))
            {
                throw new ArgumentException(DEFAULT_FORMAT_ERROR);
            }

            // try to convert the port extracted above - if no port number exists then use 80
            if (string.IsNullOrEmpty(port))
            {
                port = "80";
            }

            _port = int.Parse(port);

            if ((_port < 0) || (_port > 65535))
            {
                throw new ArgumentException("Port number must be within range: 0 <= port <= 65535");
            }
        }

        /// <summary>
        /// Server url
        /// </summary>
        public string Server
        {
            get { return _server; }
        }

        /// <summary>
        /// Protocol type
        /// </summary>
        public string Protocol
        {
            get { return _protocol; }
        }

        /// <summary>
        /// Port number
        /// </summary>
        public int Port
        {
            get { return _port; }
        }
    }
}
